home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
c
/
ldb.zip
/
SBINDER.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1991-10-18
|
11KB
|
545 lines
/*
sbinder.cpp
10-18-91
Streamable Binder: Loose Data Binder v 1.4
Copyright 1991
John W. Small
All rights reserved
PSW / Power SoftWare
P.O. Box 10072
McLean, Virginia 22102 8072 USA
John Small
Voice: (703) 759-3838
CIS: 73757,2233
*/
#include <string.h>
#include "sbinder.hpp"
void Streamable::lserror(const char *msg, unsigned id)
{
if (streamDebug)
cerr << endl
<< "Class id: " << setw(6) << id
<< " stream error - "
<< msg << endl;
}
void Streamable::serror(const char *msg)
{
if (streamDebug)
cerr << endl
<<"Class id: " << setw(6) << id
<< " &instance: "
<< (void *) this << endl
<< "Stream error - "
<< msg << endl;
}
void Streamable::swarn(const char *msg)
{
if (streamDebug)
cerr << endl
<< "Class id: " << setw(6) << id
<< " &instance: "
<< (void *) this << endl
<< "Stream warning - "
<< msg << endl;
}
#pragma argsused
StreamablE Streamable::load(istream& is,
StreamablE InstancE)
{ return InstancE; }
int Streamable::refDebug = 0;
int Streamable::streamDebug = 0;
char Streamable::memberTermChar = '\n';
#pragma argsused
Streamable::Streamable(StreamableClassRegistry& dummy,
unsigned id)
{
parenT = voiD0;
this->id = id;
refCount = streamCount = 0;
streamPos = 0L;
}
void Streamable::registerClass(unsigned id,
StreamablE (*loader)(istream& is,
StreamablE InstancE))
{
SCRegistry.registerClass(id,loader);
}
unsigned Streamable::restream()
{
unsigned underFlow = (streamPos?
refCount - streamCount : 0);
streamCount = 0;
streamPos = 0L;
if (underFlow)
swarn("restream: streamed less than "
"referenced");
return underFlow;
}
unsigned Streamable::unlink(voiD P)
{
if (refDebug)
if (refCount)
cerr << endl
<< "Class id: " << setw(6) << id
<< " &instance: "
<< (void *) this << endl
<< "Unlinking, starting refCount: "
<< refCount << endl;
else
cerr << endl
<< "Class id: " << setw(6) << id
<< " &instance: "
<< (void *) this << endl
<< "unlink() underflow" << endl;
if (refCount)
--refCount;
if (parenT == P || !refCount)
parenT = voiD0;
return refCount;
}
StreamablE Streamable::link(voiD P)
{
if (refCount >= UINT_MAX) {
if (refDebug)
cerr << endl
<< "Class id: " << setw(6) << id
<< " &instance: "
<< (void *) this << endl
<< "link() overflow" << endl;
return StreamablE0;
}
refCount++;
if (!parenT && P)
parenT = P;
if (refDebug)
cerr << endl
<< "Class id: " << setw(6) << id
<< " &instance: "
<< (void *) this << endl
<< "Adding link, new refCount: "
<< refCount << endl;
return this;
}
ostream& endm(ostream& os)
{
return os << Streamable::memberTermChar
<< flush;
}
istream& nextm(istream& is)
{
is.get();
return is;
}
int SBinder::Dfree(voiD D)
{
if (D) {
if (!((StreamablE)D)->RefCount())
delete (StreamablE) D;
return 1;
}
return 0;
}
int SBinder::Dattach(voiD D)
{
return ((((StreamablE)D)->link(this))? 1 : 0);
}
void SBinder::Ddetach(voiD D)
{
((StreamablE)D)->unlink(this);
}
ostream& SBinder::store(ostream& os)
{
unsigned i;
os << maxNodes << endm << limit << endm
<< delta << endm << nodes << endm
<< curNode << endm << flags << endm
<< FncPtrToID((GenericFnC)comparE) << endm;
if (!os)
serror("unable to store Streamable Binder");
else for (i = 0; i < nodes; i++)
Dstore(os,atGet(i));
return os;
}
StreamablE SBinder::load(istream& is, StreamablE InstancE)
{
unsigned i, maxNodes, limit, delta, nodes, curNode;
unsigned flags;
unsigned comparEID;
is >> maxNodes >> nextm >> limit >> nextm
>> delta >> nextm >> nodes >> nextm
>> curNode >> nextm >> flags >> nextm
>> comparEID >> nextm;
if (!is) {
lserror("unable to load Streamable Binder "
"header data",
ID_CLASS);
return StreamablE0;
}
flags |= BDR_OK_FREE; // reloaded nodes are dynamic!
if (!InstancE)
if ((InstancE = (StreamablE)
new SBinder(UNIQUE_STREAMABLE))
== StreamablE0) {
lserror("unable to construct "
"Streamable Binder for "
"loading",ID_CLASS);
return StreamablE0;
}
((SBindeR)InstancE)->construct(flags,maxNodes,
limit,delta);
StreamablE D;
for (i = 0; i < nodes; i++)
((SBindeR)InstancE)->insQ(
((SBindeR)InstancE)->Dload(is));
((SBindeR)InstancE)->setCurNode(curNode);
((SBindeR)InstancE)->setComparE((BDRcomparE)
IDtoFncPtr(comparEID));
return InstancE;
}
void SBinder::Dstore(ostream& os, const voiD D)
{ os << (StreamablE) D; }
voiD SBinder::Dload(istream& is)
{
StreamablE InstancE = StreamablE0;
is >> InstancE;
return (voiD) InstancE;
}
unsigned SBinder::restream()
{
unsigned result = Streamable::restream();
for (unsigned i = 0; i < nodes; i++)
((StreamablE)atGet(i))->restream();
return result;
}
SBinder::~SBinder()
{
if (flags & BDR_OK_FREE)
allFree();
else
allDel();
}
StreamableClassRegistry SCRegistry;
int StreamableClassRegistry::debug = 0;
void StreamableClassRegistry::error(char *msg, unsigned id,
StreamablE InstancE)
{
if (debug)
cerr << endl
<< "Class id: " << setw(6) << id
<< " &instance: "
<< (void *) InstancE << endl
<< "ClassRegistry error - "
<< msg << endl;
}
void StreamableClassRegistry::warn(char *msg, unsigned id,
StreamablE InstancE)
{
if (debug)
cerr << endl
<< "Class id: " << setw(6) << id
<< " &instance: "
<< (void *) InstancE << endl
<< "ClassRegistry warning - "
<< msg << endl;
}
unsigned StreamableClassRegistry::restream()
{
unsigned underFlow = InstanceLinks.Nodes();
IHRecorD R;
for (unsigned i = 0; i < underFlow; i++) {
R = (IHRecorD) InstanceLinks.atGet(i);
warn("Restream: holding pen under-linked",
R->InstancE->id,R->InstancE);
}
InstanceLinks.allFree();
return underFlow;
}
void StreamableClassRegistry::registerClass(unsigned id,
StreamablE (*loader) (istream& is,
StreamablE InstancE))
{
unsigned i;
for (i = 0; i < ClassRecords.Nodes(); i++)
if (((SCRecorD)ClassRecords[i])->id
== id)
break;
if (i < ClassRecords.Nodes())
if (((SCRecorD)ClassRecords[i])->load
== loader) {
warn("multiple registration of"
" loader",id);
return;
}
else {
error("id conflict: ",id);
return;
}
SCRecorD R = new StreamableClassRecord(id,loader);
if (!R)
error("class record memory exhausted",
id);
else if (!ClassRecords.insQ(R)) {
error("class record can't be queued",
id);
delete R;
}
}
void StreamableClassRegistry::forgetClasses()
{
ClassRecords.allFree();
InstanceLinks.allFree();
}
istream& StreamableClassRegistry::get(istream& is,
StreamablE& InstancE)
{
unsigned id, refCount, i;
long streamPos;
IHRecorD R;
InstancE = StreamablE0;
if (!(is >> id >> nextm)) {
error("unable to read id");
return is;
}
if (id == ID_StreamableRef) {
// link to previously loaded Instance
if (!(is >> streamPos >> nextm)) {
error("unable to read streamPos");
return is;
}
for (i = 0; i < InstanceLinks.Nodes(); i++)
if ((R = (IHRecorD)InstanceLinks[i])
->streamPos == streamPos) {
// found saved instance!
InstancE = R->InstancE;
if (R->refCount <= ++R->streamCount)
// discard when done!
InstanceLinks.atDel(i);
break;
}
if (!InstancE)
error("unable to establish link to"
" previously loaded class",
id);
}
else { // load instance
streamPos = is.tellg();
if (!(is >> refCount >> nextm)) {
error("unable to read refCount",id);
return is;
}
for (i = 0; i < ClassRecords.Nodes(); i++)
if (((SCRecorD)ClassRecords[i])->id
== id)
break;
if (i >= ClassRecords.Nodes()) {
error("attempted load of unknown "
"class",id);
return is;
}
if ((InstancE = (*((SCRecorD)
ClassRecords[i])->load)
(is,StreamablE0)) == StreamablE0)
{
error("unable to l